import json
import datetime

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse

from web.forms.issues import IssuesModel, IssuesReplyModelForm, InviteModelForm
from web import models
from utils.pagination import Pagination
from utils.encrypt import uid


def issues(request, project_id):
    if request.method == 'GET':
        allow_filter_name = ['status', 'issues_type', 'priority']  # 允许的筛选条件
        # get除了分页还要删选【根据用户通过get传来的参数实现
        # status=1&status=2&issues_type=1   or关系
        condition = {}
        for name in allow_filter_name:
            value_list = request.GET.getlist(name)  # [1,2,]

            if not value_list:  # 没有值 就代表用户没有传值【说明不做筛选 跳出
                continue
            # print(value_list)
            condition[f'{name}'] = value_list
        # print(condition)
        """
        condition = {status_in: [1,2], issues_type_in: [1,]}
        """

        # form = IssuesModel(request)
        #   --正常不分页
        # issues_object_list = models.Issues.objects.filter(project_id=project_id)
        # return render(request, 'issues.html', {"form": form, 'issues_object_list': issues_object_list})

        #   -- 分页
        form = IssuesModel(request)

        queryset = models.Issues.objects.filter(project_id=project_id)
        # print(queryset)
        # for q in queryset:
        # print(q)

        page_object = Pagination(request, queryset, page_size=5)

        page_queryset = page_object.page_queryset
        page_string = page_object.html()

        # 邀请成员==========================================================================
        invite_form = InviteModelForm()

        context = {
            # 'search_data': search_data,
            # "queryset": page_queryset,  # 分完页的数据
            'issues_object_list': page_queryset,
            'page_string': page_string,  # 生成的页码
            "form": form,

            'invite_form': invite_form  # 邀请成员
        }
        # 把数据传到html页面
        return render(request, 'issues.html', context)

    # print(request.POST)
    form = IssuesModel(request, data=request.POST)
    if form.is_valid():
        # 添加问题
        form.instance.project = request.bug_platform.project  # 当前项目
        form.instance.creator = request.bug_platform.user  # 当前创建项目的用户
        form.save()
        return JsonResponse({'status': True})
    return JsonResponse({'status': False, 'error': form.errors})


@csrf_exempt
def issues_detail(request, project_id, issues_id):
    """ 编辑问题 """
    issues_object = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    # instance=issues_object 编辑时显示默认【数据库中】数据
    form = IssuesModel(request, instance=issues_object)

    return render(request, 'issues_detail.html', {'form': form, 'issues_object': issues_object})


@csrf_exempt
def issues_record(request, project_id, issues_id):
    """ 初始化问题讨论操作 """
    if request.method == 'GET':
        # 获取所有的问题记录
        # models.IssuesReply.objects.filter(issues_id=issues_id, issues__project_id=project_id)
        reply_list = models.IssuesReply.objects.filter(issues_id=issues_id, issues__project=request.bug_platform.project)
        # print(reply_list.creator.username)
        # 将queryset转化为json格式【前端好显示
        data_list = []
        for row in reply_list:
            data = {
                'id': row.id,
                'reply_type_text': row.get_reply_type_display(),
                'content': row.content,
                'creator': row.creator.username,
                'datetime': row.creator_datetime.strftime('%Y-%m-%d %H:%M'),
                'parent_id': row.reply_id  # 父id
            }

            data_list.append(data)

        # print(data_list)
        return JsonResponse({'status': True, 'data': data_list})

    # 回复的ajax
    form = IssuesReplyModelForm(data=request.POST)
    if form.is_valid():
        form.instance.issues_id = issues_id
        form.instance.reply_type = 2
        form.instance.creator = request.bug_platform.user
        instance = form.save()
        info = {
            'id': instance.id,
            'reply_type_text': instance.get_reply_type_display(),
            'content': instance.content,
            'creator': instance.creator.username,
            'datetime': instance.creator_datetime.strftime('%Y-%m-%d %H:%M'),
            'parent_id': instance.reply_id  # 父id
        }
        return JsonResponse({'status': True, 'data': info})

    return JsonResponse({'status': True, 'error': form.errors})


@csrf_exempt
def issues_change(request, project_id, issues_id):
    """ 评论 & 回复 & 生成操作记录   """
    # 拿到当前数据库对象
    # issues_object = models.Issues.objects.filter(id=issues_id, project=request.bug_platform.project).first()
    issues_object = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    post_dict = json.loads(request.body.decode('utf-8'))  # 前端传来的数据
    """
    {'name': 'issues_type', 'value': '2'}
    {'name': 'subject', 'value': 'hello 你好'}
    """

    # print(post_dict)

    name = post_dict.get('name')
    value = post_dict.get('value')
    field_object = models.Issues._meta.get_field(name)  # 数据库中字段的属性

    def create_reply_record(content):
        new_object = models.IssuesReply.objects.create(
            reply_type=1,
            issues=issues_object,
            content=change_record,
            creator=request.bug_platform.user,
        )
        new_reply_dict = {
            'id': new_object.id,
            'reply_type_text': new_object.get_reply_type_display(),
            'content': new_object.content,
            'creator': new_object.creator.username,
            'datetime': new_object.creator_datetime.strftime('%Y-%m-%d %H:%M'),
            'parent_id': new_object.reply_id  # 父id
        }

        return new_reply_dict

    # 数据获取后1， 更新数据库字段内容
    # 1.1 文本【 标题 & 实践输入的
    if name in ['subject', 'desc', 'start_date', 'end_date']:
        """
    # 存储的是文本
    """
        if not value:  # 判断输入的值是否为空
            if not field_object.null:  # 判断数据库中该字段能不能为空
                return JsonResponse({'status': False, 'error': '值不能为空'})
            setattr(issues_object, name, None)
            issues_object.save()  # 更新
            # 数据库跟新后生成操作记录： xx修改成空
            change_record = f'{field_object.verbose_name}更新成空'
        else:
            setattr(issues_object, name, value)
            issues_object.save()
            # 数据库跟新后生成操作记录： xx修改成value
            change_record = f'{field_object.verbose_name}更新成: {value}'

        # 生成记录的数据 上面的函数create_reply_record
        data = create_reply_record(change_record)
        return JsonResponse({'status': True, 'data': data})
        # return JsonResponse({'status': True})
    # 1.2 FK字段【 关联的数据、 【指派特殊    / 报错
    if name in ['issues_type', 'module', 'assign', 'parent']:
        # 用户选择为空
        if not value:
            # 数据不允许为空
            if not field_object.null:
                return JsonResponse({'status': False, 'error': '值不能为空'})
            # 允许为空
            setattr(issues_object, name, None)
            issues_object.save()
            change_record = f'{field_object.verbose_name}选择了空'
        else:  # 用户选择不为空
            if name == 'assign':  # 指派
                # 判断是否是当前的创建者
                if value == str(request.bug_platform.project.creator_id):
                    instance = request.bug_platform.project.creator
                else:
                    # 是否是当前项目的参与者
                    project_user_object = models.ProjectUser.objects.filter(project_id=project_id, user_id=value).first()
                    if project_user_object:  # 有值就说明是参与者
                        instance = project_user_object.user
                    else:
                        instance = None
                if not instance:
                    return JsonResponse({'status': False, 'error': '您选择的值不存在'})
                setattr(issues_object, name, instance)  # 1/2/3/4
                issues_object.save()
                change_record = f'{field_object.verbose_name}更新成{str(instance)}'  # 根据value到数据库获取对应的文本
            else:  # 除了指派以外的
                # 判断输入的值是否是当前的项目的 当前问题的值
                # 跨表查询根据数据库的to后面的表查
                # instance = field_object.rel.model.objects.filter(id=value, project_id=project_id).first()
                instance = field_object.remote_field.model.objects.filter(id=value, project_id=project_id).first()  # django新版和上面旧版的区别

                if not instance:
                    return JsonResponse({'status': False, 'error': '选择值不存在'})

                setattr(issues_object, name, instance)  # 1/2/3/4
                issues_object.save()
                # 数据库跟新后生成操作记录： xx修改成value
                change_record = f'{field_object.verbose_name}更新成{str(instance)}'  # 根据value到数据库获取对应的文本

                # 生成记录的数据
            data = create_reply_record(change_record)
            return JsonResponse({'status': True, 'data': data})
            # return JsonResponse({'status': True})
        # 1.3 choices字段【 下拉
    if name in ['priority', 'status', 'mode']:
        selected_text = None
        for key, text in field_object.choices:  # 字段可直接点属性拿到值
            if str(key) == value:
                selected_text = text

        if not selected_text:  # 不存在
            return JsonResponse({'status': False, 'error': '选择值不存在'})
        else:
            setattr(issues_object, name, value)
            issues_object.save()
            change_record = f'{field_object.verbose_name}更新成{selected_text}'  # 根据value到数据库获取对应的文本

            data = create_reply_record(change_record)
            return JsonResponse({'status': True, 'data': data})
            # return JsonResponse({'status': True})
        # 1.4 M2M字段【 多选     // 报错了
    if name == 'attention':
        # {'name': 'attention', 'value': ['9','2']}
        if not isinstance(value, list):
            return JsonResponse({'status': False, 'error': '数据格式错误'})
        # 空 【 清空关联的表
        if not value:
            issues_object.attention.set([])
            issues_object.save()
            change_record = f'{field_object.verbose_name}更新为空'  # 根据value到数据库获取对应的文本
        else:
            # value : ['1','2','2']  id是否是创建者 or 参与者
            # 获取当前项目的所有成员
            project_user_list = models.ProjectUser.objects.filter(project=request.bug_platform.project)
            # key:项目参与者id value:项目参与者姓名
            user_dict = {str(request.bug_platform.project.creator_id): request.bug_platform.project.creator.username}
            for item in project_user_list:
                user_dict[str(item.user_id)] = item.user.username

            username_list = []
            # 循环判断前端传来的value
            for user_id in value:
                username = user_dict.get(str(user_id))  # 成员用户名
                if not username:
                    return JsonResponse({'status': False, 'error': '用户数据错误，刷新试试'})
                # 正确
                username_list.append(username)

            issues_object.attention.set(value)
            issues_object.save()
            # 操作记录
            change_record = f'{field_object.verbose_name}更新为: {",".join(username_list)}'

        data = create_reply_record(change_record)
        # print(data)
        return JsonResponse({'status': True, 'data': data})
        # return JsonResponse({'status': True})
        # 2，生成操作记录
    return JsonResponse({'status': False, 'error': '滚犊子'})


def invite_url(request, project_id):
    """ 生成 邀请成员码 """

    form = InviteModelForm(data=request.POST)
    if form.is_valid():
        # form.save()
        """
        1, 创建一个随机的邀请码
        2，将验证码保存到数据库
        3，限制：只有创建者才能邀请 | 
        """
        # 判断当前用户是否是当前的项目创建者
        if request.bug_platform.user != request.bug_platform.project.creator:
            form.add_error('period', '无权创建邀请码')

        # 根据当前用户手机号 创建一个随机邀请码
        random_invite_code = uid(request.bug_platform.user.mobile_phone)

        # 保存到数据库
        form.instance.project = request.bug_platform.project
        form.instance.code = random_invite_code
        form.instance.creator = request.bug_platform.user
        form.save()

        # 将生成好的邀请码返回给前端，前端页面展示出来
        url_path = reverse('invite_join', kwargs={'code': random_invite_code})  # 反向生成邀请码的url
        #        http               http://127.0.0.1:8000/
        url = f'{request.scheme}://{request.get_host()}{url_path}'
        # print(random_invite_code)
        # print(url_path)
        # print(url)
        return JsonResponse({'status': True, 'data': url})

    return JsonResponse({'status': False, 'error': form.errors})


def invite_join(request, code):
    """ 被邀请者访问的url """
    # 查询数据库
    invite_object = models.ProjectInvite.objects.filter(code=code).first()
    # 判断邀请码是否存在
    if not invite_object:
        return render(request, 'invite_join.html', {'error': '邀请码不存在'})

    # 判断邀请者是否是当前项目创建者
    if invite_object.project.creator == request.bug_platform.user:
        return render(request, 'invite_join.html', {'error': '创建者无需在加入项目'})

    # 判断邀请者是否是当前项目的成员
    exists = models.ProjectUser.objects.filter(project=invite_object.project, user=request.bug_platform.user).exists()
    if exists:
        return render(request, 'invite_join.html', {'error': '已是当前项目的成员，无需再加入'})

    # 项目最多允许成员【要进人这个项目的创建者的价格策略限制
    # max_member = request.bug_platform.price_policy.project_member   # 这个是当前登录用户的价格策略

    # 项目的创建者
    # invite_object.project.creator
    # 该用户的最后交易记录
    max_transaction = models.Transaction.objects.filter(user=invite_object.project.creator).order_by('-id').first()
    # 是否已经过期，如果已经过期就使用免费额度
    if max_transaction.price_policy.category == 1:
        # 免费
        # models.PricePolicy.objects.filter(category=1).first()
        max_member = max_transaction.price_policy.project_member
    else:
        # 不是免费的就要判断时间是否过期
        current_datetime = datetime.datetime.now()
        if max_transaction.end_datetime < current_datetime:
            # 过期
            free_object = models.PricePolicy.objects.filter(category=1).first()
            max_member = free_object.project_member
        else:  # 没有过期
            max_member = max_transaction.price_policy.project_member

    # 目前所有成员【 没有包含创建者
    current_member = models.ProjectUser.objects.filter(project=invite_object.project).count()
    current_member += 1  # 加上创建者
    if current_member >= max_member:
        return render(request, 'invite_join.html', {'error': '项目成员超过限制，无法加入，请升级套餐'})

    # 邀请码是否过期
    current_datetime = datetime.datetime.now()  # 当前时间
    # 截止时间   = 创建时间 + 限制的时间【 分钟 * 60
    limit_datetime = invite_object.create_datetime + datetime.timedelta(minutes=invite_object.period)
    if current_datetime > limit_datetime:
        return render(request, 'invite_join.html', {'error': '邀请码已过期'})

    # 邀请的数量限制
    if invite_object.count:  # 有值就代表有数量限制
        #   已经使用的数量         &       数量限制
        if invite_object.use_count >= invite_object.count:  # 超出限制
            return render(request, 'invite_join.html', {'error': '邀请码数量使用完'})
        # 否则就是没有超出限制 【 没有超出就要用一次数量要加一
        invite_object.use_count += 1
        invite_object.save()
        # 添加到数据库保存
        models.ProjectUser.objects.create(user=request.bug_platform.user, project=invite_object.project)
        invite_object.project.join_count += 1  # 邀请成功后 数据库参与人数应该加一
        invite_object.save()
        return render(request, 'invite_join.html', {'project': invite_object.project})

    else:  # 否则就是没有数量限制
        # 添加到数据库保存
        models.ProjectUser.objects.create(user=request.bug_platform.user, project=invite_object.project)
        invite_object.project.join_count += 1  # 邀请成功后 数据库参与人数应该加一
        invite_object.save()
        return render(request, 'invite_join.html', {'project': invite_object.project})
